/*
 * TextureMgr.cpp
 * Author: Johan Kristins
 *	
 */

#include "TextureMgr.h"

TextureMgr::TextureMgr()
{

};

TextureMgr::~TextureMgr()
{
	
};

bool TextureMgr::Init()
{
	m_mTextures.clear();
	m_TextureLookup.clear();

	return true;
};

void TextureMgr::Close()
{
	if (m_mTextures.size() > 0)
	{
		std::map<unsigned int, Texture*>::iterator texture_iter = m_mTextures.begin();
		while(texture_iter != m_mTextures.end())
		{
			delete (*texture_iter).second;
			texture_iter++;
		};
	};
	m_mTextures.clear();
	m_TextureLookup.clear();
};

Texture* TextureMgr::LoadTexture(const char* filename)
{
	if (filename == "")
	{
		return NULL;
	};

	stdext::hash_map<const char*, Texture*>::iterator hash_iter = m_TextureLookup.find(filename);
	if (hash_iter != m_TextureLookup.end())
	{
		return (*hash_iter).second;
	};

	Texture* newTexture = new Texture();
	ReadFile(newTexture, filename);

	m_mTextures.insert(std::make_pair<unsigned int, Texture*>(newTexture->m_iID, newTexture));
	m_TextureLookup.insert(std::make_pair<const char*, Texture*>(filename, newTexture));

	return newTexture;
};

void TextureMgr::ReadFile(Texture* p_Texture, const char* filename)
{
	FILE * inStream;

	fopen_s(&inStream, filename, "rb");

	//If failed to open.
	if(!inStream)
	{
		return;
	}

	unsigned char byteGarbage;
	short int int16Garbage;

	//Read the fileheader.
	fread(&byteGarbage, sizeof(unsigned char), 1, inStream);
	fread(&byteGarbage, sizeof(unsigned char), 1, inStream);
	fread(&byteGarbage, sizeof(unsigned char), 1, inStream);
	fread(&int16Garbage, sizeof(short int), 1, inStream);
	fread(&int16Garbage, sizeof(short int), 1, inStream);
	fread(&byteGarbage, sizeof(unsigned char), 1, inStream);
	fread(&int16Garbage, sizeof(short int), 1, inStream);
	fread(&int16Garbage, sizeof(short int), 1, inStream);
	fread(&p_Texture->m_iWidth, sizeof(short int), 1, inStream);
	fread(&p_Texture->m_iHeight, sizeof(short int), 1, inStream);
	fread(&p_Texture->m_cBitMode, sizeof(unsigned char), 1, inStream);
	fread(&byteGarbage, sizeof(unsigned char), 1, inStream);

	int pixelCount = p_Texture->m_iWidth*p_Texture->m_iHeight;
	unsigned char pixelSwap;

	//check if the files width and height is power of 2
	if ( ((p_Texture->m_iWidth & (p_Texture->m_iWidth - 1)) != 0) || ((p_Texture->m_iHeight & (p_Texture->m_iHeight - 1)) != 0) )
	{
		fclose(inStream);
		return;
	}

	//Different loading depending if the image uses an extra byte for alpha or not.
	switch(p_Texture->m_cBitMode)
	{
	case 24:
		p_Texture->m_pacPixelData = new unsigned char[pixelCount*3];
		fread(p_Texture->m_pacPixelData, sizeof(unsigned char), pixelCount*3, inStream);

		//Swaps pixel from BGR to RGB
		for(int i = 0; i < pixelCount*3; i+=3)
		{
			pixelSwap = p_Texture->m_pacPixelData[i];
			p_Texture->m_pacPixelData[i] = p_Texture->m_pacPixelData[i+2];
			p_Texture->m_pacPixelData[i+2] = pixelSwap;
		}
		break;

	case 32:
		p_Texture->m_pacPixelData = new unsigned char[pixelCount*4];
		fread(p_Texture->m_pacPixelData, sizeof(unsigned char), pixelCount*4, inStream);

		//Swaps pixel from BGRA to RGBA
		for(int i = 0; i < pixelCount*4; i+=4)
		{
			pixelSwap = p_Texture->m_pacPixelData[i];
			p_Texture->m_pacPixelData[i] = p_Texture->m_pacPixelData[i+2];
			p_Texture->m_pacPixelData[i+2] = pixelSwap;
		}
		break;

	default:
		return;
	}
	fclose(inStream);
};